package statistics;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import main.Simulator;
import main.Util;
import LBJ2.util.StudentT;
import event.FinishSimulationEvent;
import event.ICVazaoMediaEvent;

public class ICVazaoMediaStatistics {

	private static final double LARGURA_MINIMA = 0.1;

	public final static double ALFA = 0.1;
	
	Simulator simulator;
	List<ArrayList<Double>> amostrasRodadas = new ArrayList<ArrayList<Double>>();
	List<ArrayList<Double>> coletasRodada = new ArrayList<ArrayList<Double>>();
	
	int numRodadaAtual = 0;
	int numColetasAtual;
	int numRodadaTotal;
	int numColetasTotal;
	double intervalo;
	int numSessoes;
	double inicioRodada;

	public ICVazaoMediaStatistics(Simulator simulator) {
		this.simulator = simulator;
		this.numRodadaTotal = simulator.getProperties().getNumeroRodadas();
		this.numColetasTotal = simulator.getProperties().getNumeroColetas();
		this.intervalo = simulator.getProperties().getIntervaloEntreColetas();
		this.numSessoes = simulator.getProperties().getN1() + simulator.getProperties().getN2();
		
		for (int i = 0; i < this.numSessoes; i++) {
			this.amostrasRodadas.add(new ArrayList<Double>());
			this.coletasRodada.add(new ArrayList<Double>());
		}
		
		inicioRodada();
	}
	
	public void collect() {
		for (int i = 0; i < this.numSessoes; i++) {
			long packetsReceiveds = simulator.getReceivers().get(i).getPacketsReceiveds();
			double time = Util.convertMillisToSeconds(simulator.getTime() - inicioRodada);
			double amostra = packetsReceiveds / time;
			this.coletasRodada.get(i).add(amostra);
		}
		
		numColetasAtual++;
		
		if (numColetasAtual == numColetasTotal) {
			fimRodada();
		}
		
		simulator.addEvent(new ICVazaoMediaEvent(simulator.getTime() + intervalo));
	}
	
	private void inicioRodada() {
		inicioRodada = simulator.getTime();
		numColetasAtual = 0;
		numRodadaAtual++;
		
		for (int i = 0; i < numSessoes; i++) {
			coletasRodada.get(i).clear();
			simulator.getReceivers().get(i).setPacketsReceiveds(0);
		}
	}
	
	
	private void fimRodada() {
		for (int i = 0; i < numSessoes; i++) {
			double media = 0;
			for (int j = 0; j < numColetasTotal; j++) {
				media += coletasRodada.get(i).get(j);
			}
			media /= numColetasTotal;
			amostrasRodadas.get(i).add(media);
		}

		if (numRodadaTotal == 0) {
			if (areIntervalsLessEnough())
				simulator.addEvent(new FinishSimulationEvent(simulator.getTime()));
		}
		else if (numRodadaAtual == numRodadaTotal) {
			simulator.addEvent(new FinishSimulationEvent(simulator.getTime()));
		}
		
		inicioRodada();
	}
	
	private boolean areIntervalsLessEnough() {
		if(numRodadaAtual < 2) return false;
		
		for (int i=0; i<amostrasRodadas.size(); i++) {
			double[] amostras = Util.convertDoubleToArray(amostrasRodadas.get(i));
			double[] ic = StudentT.confidenceInterval(amostras, ALFA);
			
			if (2*ic[1] / ic[0] > LARGURA_MINIMA)
				return false;
		}
		
		return true;
	}

	public void saveAsFile() {
		StringBuffer buffer = new StringBuffer();
		buffer.append("Tempo de execução: "+Util.convertMillisToSeconds(System.currentTimeMillis()-simulator.getStartRealTime())+" s\n");
		buffer.append("Tempo de simulação: "+Util.convertMillisToSeconds(simulator.getTime())+" s\n");
		buffer.append("Número de Rodadas: "+(numRodadaAtual-1)+"\n");
		buffer.append("Estimativa da Fase Transiente: "+simulator.getProperties().getTransiente()+" s\n\n");
		
		for (int i=0; i<amostrasRodadas.size(); i++) {
			double[] amostras = Util.convertDoubleToArray(amostrasRodadas.get(i));
			double[] ic = StudentT.confidenceInterval(amostras, ALFA);
			buffer.append("Sessão "+i+"\n");
			buffer.append("Amostras: "+Util.prettyPrint(amostrasRodadas.get(i))+"\n");
			buffer.append("Média: "+Util.prettyPrint(ic[0])+"\n");
			buffer.append("Largura do Intervalo: "+Util.prettyPrint(2*ic[1])+" ("+Util.prettyPrint(100*2*ic[1]/ic[0])+" %)\n");
			buffer.append("Intervalo de Confiança: ["+Util.prettyPrint(ic[0]-ic[1])+", "+Util.prettyPrint(ic[0]+ic[1])+"]\n");
			buffer.append("\n");
		}
		
		try {
			String filename = simulator.getProperties().getName()+ "-" + "IC" + ".txt";
			String dir = simulator.getProperties().getDirectoryToSave();
			File file = dir != null ? new File(new File(dir), filename) : new File(filename);
			FileWriter writer = new FileWriter(file);
			writer.write(buffer.toString());
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
